package com.testingedu.filter;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.testingedu.jdbcDao.TOperateDao;
import com.testingedu.model.TUser;

public class AdminActionInvoke extends ActionInvoke {
	private static final Log log = LogFactory.getLog(AdminActionInvoke.class);
	private static final String actionConfig = "adminAction.properties";
	private static final Map<String, String> actionMapping = new HashMap<String, String>();
	private static final String permissionConfig = "permission.properties";
	private static final List<String> ignoreURIsBeforeLogin = new ArrayList<String>();
	private static final List<String> ignoreURIsAfterLogin = new ArrayList<String>();
	static {
		init();
	}

	private static void init() {
		Properties adminProperties = new Properties();
		Properties permissionProperties = new Properties();
		try {
			adminProperties.load(AdminActionInvoke.class.getClassLoader()
					.getResourceAsStream(actionConfig));
			permissionProperties.load(AdminActionInvoke.class.getClassLoader()
					.getResourceAsStream(permissionConfig));
			Set<Object> adminKeys = adminProperties.keySet();
			for (Object object : adminKeys) {
				actionMapping.put((String) object, (String) adminProperties
						.getProperty((String) object));
			}
			String ignoreBefore = permissionProperties
					.getProperty("ignoreURIBeforeLogin");
			String ignoreAfter = permissionProperties
					.getProperty("ignoreURIAfterLogin");
			if (ignoreBefore != null && ignoreBefore.trim().length() > 0) {
				for (String str : ignoreBefore.split(",")) {
					ignoreURIsBeforeLogin.add(str.trim());
				}
			}
			if (ignoreAfter != null && ignoreAfter.trim().length() > 0) {
				for (String str : ignoreAfter.split(",")) {
					ignoreURIsAfterLogin.add(str.trim());
				}
			}
		} catch (Exception e) {
			log.error("初始化后台配置文件失败：" + e);
		}
	}

	@Override
	public void invoke() throws Exception {
		if (!baseURISecurity(5)) { // 不存在的url请求范围
			request.getRequestDispatcher(PAGE_404).forward(request, response);
		} else {
			String action = uris[uris.length - 2];// 获取请求action的名称
			String method = uris[uris.length - 1];// 获取请求action中的方法
			if (ignoreURIsBeforeLogin.contains(method)
					|| ignoreURIsBeforeLogin.contains(action + "/" + method)) { // 不需登陆验证的action
				execute(action, method);
			} else {
				if (!isLogin(request)) {
					request
							.getRequestDispatcher(
									"/WEB-INF/admin/jsp/login.jsp").forward(
									request, response);
				} else {
					if (ignoreURIsAfterLogin.contains(method)
							&& "admin".equals(action)) { // 登陆后不需验证权限的url
						execute(action, method);
					} else {
						if (validatePermission(request)) { // 验证权限
							execute(action, method);
						} else {
							request.setAttribute("message", "没有权限");
							request.getRequestDispatcher(PAGE_ERROR).forward(
									request, response);
						}
					}
				}
			}
		}
	}

	/**
	 * 验证此登陆用户是否有权限请求该功能
	 * 
	 * @param request
	 * @return
	 */
	private boolean validatePermission(HttpServletRequest request)
			throws Exception {
		return TOperateDao.validatePermission(request.getRequestURI(),
				getSessionUser().getId());
	}

	/**
	 * 封装请求参数（包括文件），将request、response注入到RequestContext中，执行对应的action及方法
	 * 
	 * @param action
	 *            请求的action名称
	 * @param method
	 *            action对应的方法名称
	 * @throws Exception
	 */
	private void execute(String action, String method) throws Exception {
		String className = actionMapping.get(action); // 获取action对应的类全称
		try {
			Class<?> clazz = Class.forName(className);
			Method execM = clazz.getDeclaredMethod(PREFIX + method);
			Object actionO = clazz.newInstance();
			autoEncoding();
			setReqAndRespToAction(clazz, actionO);
			setBeanToAction(clazz, actionO, null);
			try {
				execM.invoke(actionO);
			} catch (Exception e) {
				log.error("执行action时出错了：" + e);
				request.setAttribute("message", "程序执行出错了，请重试或通知管理员");
				request.getRequestDispatcher(PAGE_ERROR).forward(request,
						response);
			}
		} catch (Exception e) { // 没有对应的action或方法
			request.getRequestDispatcher(PAGE_404).forward(request, response);
		}
	}

	/**
	 * 验证用户是否已经登陆
	 * 
	 * @param request
	 * @return
	 */
	private boolean isLogin(HttpServletRequest request) {
		if (getSessionUser() != null) {
			return true;
		}
		return false;
	}

	/**
	 * 得到session中的用户
	 * 
	 * @return
	 */
	private TUser getSessionUser() {
		return (TUser) request.getSession().getAttribute("testingedu_admin");
	}
}
